<!doctype html><html lang=cn-zh><head><meta charset=UTF-8><meta name=viewport content="width=device-width,initial-scale=1"><meta http-equiv=X-UA-Compatible content="IE=edge"><style type=text/css>body{font-family:monospace}</style><title>Golang实现Windows系统用户和密码校验</title>
<meta name=description content="A blog maintained by Vimiix."><link rel=stylesheet href=/css/style.css><script>var _hmt=_hmt||[];(function(){var e,t=document.createElement("script");t.src="https://hm.baidu.com/hm.js?7c24231917964240bae97e813810620c",e=document.getElementsByTagName("script")[0],e.parentNode.insertBefore(t,e)})()</script></head><body><header>====================<br>== Hi, I'm Vimiix ==<br>====================<div style=float:right;color:gray;font-size:x-large>Get hands dirty.</div><br><p><nav><a href=https://www.vimiix.com/><b>首页</b></a>.
<a href=/posts/><b>文章列表</b></a>.
<a href=/projects/><b>开源项目</b></a>.
<a href=/tags/><b>标签</b></a>.
<a href=/friends/><b>友链</b></a>.
<a href=/about/><b>关于我</b></a>.
<a href=/index.xml><b>RSS</b></a>.</nav></p></header><main><article><h1>Golang实现Windows系统用户和密码校验</h1><b><time>2021.03.22 16:22</time></b>
<a href=/tags/note>note</a>
<a href=/tags/windows>windows</a>
<a href=/tags/golang>golang</a><div><p>本质上是通过调用 windows 的一个 API —— <a href=https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-logonuserw><code>LogonUserW</code></a> ，来实现对于用户密码的校验。</p><blockquote><p>仅适用于在本地校验，不支持远程连接校验</p></blockquote><p>用一个示例代码来进行说明，下面是目录结构中，<code>main.go</code> 是程序入口文件，auth 包中，我们仅实现 windows 系统的校验代码，其他平台不属于本文介绍内容，就直接返回 nil 即可。</p><h4 id=目录结构>目录结构</h4><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>.
</span></span><span style=display:flex><span>├── auth
</span></span><span style=display:flex><span>│   ├── auth.go
</span></span><span style=display:flex><span>│   └── auth_windows.go
</span></span><span style=display:flex><span>├── go.mod
</span></span><span style=display:flex><span>└── main.go
</span></span></code></pre></div><h4 id=源代码-srchttpsgithubcomvimiixauthdemo>源代码 <a href=https://github.com/vimiix/authDemo>[src]</a></h4><ul><li>main.go</li></ul><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#f92672>package</span> <span style=color:#a6e22e>main</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#f92672>import</span> (
</span></span><span style=display:flex><span>    <span style=color:#e6db74>&#34;flag&#34;</span>
</span></span><span style=display:flex><span>    <span style=color:#e6db74>&#34;fmt&#34;</span>
</span></span><span style=display:flex><span>    <span style=color:#e6db74>&#34;os&#34;</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>    <span style=color:#e6db74>&#34;github.com/vimiix/authDemo/auth&#34;</span>
</span></span><span style=display:flex><span>)
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>func</span> <span style=color:#a6e22e>main</span>() {
</span></span><span style=display:flex><span>    <span style=color:#a6e22e>user</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>flag</span>.<span style=color:#a6e22e>String</span>(<span style=color:#e6db74>&#34;u&#34;</span>, <span style=color:#e6db74>&#34;&#34;</span>, <span style=color:#e6db74>&#34;username&#34;</span>)
</span></span><span style=display:flex><span>    <span style=color:#a6e22e>password</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>flag</span>.<span style=color:#a6e22e>String</span>(<span style=color:#e6db74>&#34;p&#34;</span>, <span style=color:#e6db74>&#34;&#34;</span>, <span style=color:#e6db74>&#34;password&#34;</span>)
</span></span><span style=display:flex><span>    <span style=color:#a6e22e>flag</span>.<span style=color:#a6e22e>Parse</span>()
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>    <span style=color:#66d9ef>if</span> <span style=color:#f92672>*</span><span style=color:#a6e22e>user</span> <span style=color:#f92672>==</span> <span style=color:#e6db74>&#34;&#34;</span> <span style=color:#f92672>||</span> <span style=color:#f92672>*</span><span style=color:#a6e22e>password</span> <span style=color:#f92672>==</span> <span style=color:#e6db74>&#34;&#34;</span> {
</span></span><span style=display:flex><span>        <span style=color:#a6e22e>fmt</span>.<span style=color:#a6e22e>Println</span>(<span style=color:#e6db74>&#34;Both user and password should be specify&#34;</span>)
</span></span><span style=display:flex><span>        <span style=color:#a6e22e>fmt</span>.<span style=color:#a6e22e>Printf</span>(<span style=color:#e6db74>&#34;Usage: %s -u [username] -p [password]\n&#34;</span>, <span style=color:#a6e22e>os</span>.<span style=color:#a6e22e>Args</span>[<span style=color:#ae81ff>0</span>])
</span></span><span style=display:flex><span>        <span style=color:#66d9ef>return</span>
</span></span><span style=display:flex><span>    }
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>    <span style=color:#a6e22e>err</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>auth</span>.<span style=color:#a6e22e>Auth</span>(<span style=color:#f92672>*</span><span style=color:#a6e22e>user</span>, <span style=color:#f92672>*</span><span style=color:#a6e22e>password</span>)
</span></span><span style=display:flex><span>    <span style=color:#66d9ef>if</span> <span style=color:#a6e22e>err</span> <span style=color:#f92672>!=</span> <span style=color:#66d9ef>nil</span> {
</span></span><span style=display:flex><span>        <span style=color:#a6e22e>fmt</span>.<span style=color:#a6e22e>Printf</span>(<span style=color:#e6db74>&#34;Auth failed.\nError message:%v\n&#34;</span>, <span style=color:#a6e22e>err</span>)
</span></span><span style=display:flex><span>    } <span style=color:#66d9ef>else</span> {
</span></span><span style=display:flex><span>        <span style=color:#a6e22e>fmt</span>.<span style=color:#a6e22e>Println</span>(<span style=color:#e6db74>&#34;Auth successfully&#34;</span>)
</span></span><span style=display:flex><span>    }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><ul><li>auth_windows.go</li></ul><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#75715e>// +build windows
</span></span></span><span style=display:flex><span><span style=color:#75715e></span>
</span></span><span style=display:flex><span><span style=color:#f92672>package</span> <span style=color:#a6e22e>auth</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#f92672>import</span> (
</span></span><span style=display:flex><span>    <span style=color:#e6db74>&#34;syscall&#34;</span>
</span></span><span style=display:flex><span>    <span style=color:#e6db74>&#34;unsafe&#34;</span>
</span></span><span style=display:flex><span>)
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#75715e>// 下面的常量定义在 Winbase.h 头文件中
</span></span></span><span style=display:flex><span><span style=color:#75715e>// logon type
</span></span></span><span style=display:flex><span><span style=color:#75715e></span><span style=color:#66d9ef>const</span> (
</span></span><span style=display:flex><span>    <span style=color:#a6e22e>LOGON32_LOGON_INTERACTIVE</span> = <span style=color:#ae81ff>2</span>
</span></span><span style=display:flex><span>)
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#75715e>// logon provider
</span></span></span><span style=display:flex><span><span style=color:#75715e></span><span style=color:#66d9ef>const</span> (
</span></span><span style=display:flex><span>    <span style=color:#a6e22e>LOGON32_PROVIDER_DEFAULT</span> = <span style=color:#ae81ff>0</span>
</span></span><span style=display:flex><span>)
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>var</span> (
</span></span><span style=display:flex><span>    <span style=color:#a6e22e>modAdvApi32</span>    = <span style=color:#a6e22e>syscall</span>.<span style=color:#a6e22e>NewLazyDLL</span>(<span style=color:#e6db74>&#34;advapi32.dll&#34;</span>)
</span></span><span style=display:flex><span>    <span style=color:#a6e22e>procLogonUserW</span> = <span style=color:#a6e22e>modAdvApi32</span>.<span style=color:#a6e22e>NewProc</span>(<span style=color:#e6db74>&#34;LogonUserW&#34;</span>)
</span></span><span style=display:flex><span>)
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>func</span> <span style=color:#a6e22e>Auth</span>(<span style=color:#a6e22e>user</span>, <span style=color:#a6e22e>password</span> <span style=color:#66d9ef>string</span>) <span style=color:#66d9ef>error</span> {
</span></span><span style=display:flex><span>    <span style=color:#66d9ef>return</span> <span style=color:#66d9ef>nil</span>
</span></span><span style=display:flex><span>}
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>func</span> <span style=color:#a6e22e>logon</span>(<span style=color:#a6e22e>username</span> <span style=color:#66d9ef>string</span>, <span style=color:#a6e22e>domain</span> <span style=color:#66d9ef>string</span>, <span style=color:#a6e22e>password</span> <span style=color:#66d9ef>string</span>) (<span style=color:#a6e22e>syscall</span>.<span style=color:#a6e22e>Token</span>, <span style=color:#66d9ef>error</span>) {
</span></span><span style=display:flex><span>    <span style=color:#66d9ef>var</span> <span style=color:#a6e22e>token</span> <span style=color:#a6e22e>syscall</span>.<span style=color:#a6e22e>Token</span>
</span></span><span style=display:flex><span>    <span style=color:#a6e22e>err</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>logonUserW</span>(
</span></span><span style=display:flex><span>        <span style=color:#a6e22e>syscall</span>.<span style=color:#a6e22e>StringToUTF16Ptr</span>(<span style=color:#a6e22e>username</span>),
</span></span><span style=display:flex><span>        <span style=color:#a6e22e>syscall</span>.<span style=color:#a6e22e>StringToUTF16Ptr</span>(<span style=color:#a6e22e>domain</span>),
</span></span><span style=display:flex><span>        <span style=color:#a6e22e>syscall</span>.<span style=color:#a6e22e>StringToUTF16Ptr</span>(<span style=color:#a6e22e>password</span>),
</span></span><span style=display:flex><span>        <span style=color:#a6e22e>LOGON32_LOGON_INTERACTIVE</span>,
</span></span><span style=display:flex><span>        <span style=color:#a6e22e>LOGON32_PROVIDER_DEFAULT</span>,
</span></span><span style=display:flex><span>        <span style=color:#f92672>&amp;</span><span style=color:#a6e22e>token</span>,
</span></span><span style=display:flex><span>    )
</span></span><span style=display:flex><span>    <span style=color:#66d9ef>if</span> <span style=color:#a6e22e>err</span> <span style=color:#f92672>!=</span> <span style=color:#66d9ef>nil</span> {
</span></span><span style=display:flex><span>        <span style=color:#66d9ef>return</span> <span style=color:#ae81ff>0</span>, <span style=color:#a6e22e>err</span>
</span></span><span style=display:flex><span>    }
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>    <span style=color:#66d9ef>return</span> <span style=color:#a6e22e>token</span>, <span style=color:#66d9ef>nil</span>
</span></span><span style=display:flex><span>}
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>func</span> <span style=color:#a6e22e>logonUserW</span>(<span style=color:#a6e22e>username</span> <span style=color:#f92672>*</span><span style=color:#66d9ef>uint16</span>, <span style=color:#a6e22e>domain</span> <span style=color:#f92672>*</span><span style=color:#66d9ef>uint16</span>, <span style=color:#a6e22e>password</span> <span style=color:#f92672>*</span><span style=color:#66d9ef>uint16</span>, <span style=color:#a6e22e>logonType</span> <span style=color:#66d9ef>uint32</span>,
</span></span><span style=display:flex><span>    <span style=color:#a6e22e>logonProvider</span> <span style=color:#66d9ef>uint32</span>, <span style=color:#a6e22e>outToken</span> <span style=color:#f92672>*</span><span style=color:#a6e22e>syscall</span>.<span style=color:#a6e22e>Token</span>) <span style=color:#66d9ef>error</span> {
</span></span><span style=display:flex><span> <span style=color:#a6e22e>ret</span>, <span style=color:#a6e22e>_</span>, <span style=color:#a6e22e>err</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>syscall</span>.<span style=color:#a6e22e>Syscall6</span>(
</span></span><span style=display:flex><span>  <span style=color:#a6e22e>procLogonUserW</span>.<span style=color:#a6e22e>Addr</span>(),
</span></span><span style=display:flex><span>  <span style=color:#ae81ff>6</span>,
</span></span><span style=display:flex><span>  uintptr(<span style=color:#a6e22e>unsafe</span>.<span style=color:#a6e22e>Pointer</span>(<span style=color:#a6e22e>username</span>)),
</span></span><span style=display:flex><span>  uintptr(<span style=color:#a6e22e>unsafe</span>.<span style=color:#a6e22e>Pointer</span>(<span style=color:#a6e22e>domain</span>)),
</span></span><span style=display:flex><span>  uintptr(<span style=color:#a6e22e>unsafe</span>.<span style=color:#a6e22e>Pointer</span>(<span style=color:#a6e22e>password</span>)),
</span></span><span style=display:flex><span>  uintptr(<span style=color:#a6e22e>logonType</span>),
</span></span><span style=display:flex><span>  uintptr(<span style=color:#a6e22e>logonProvider</span>),
</span></span><span style=display:flex><span>  uintptr(<span style=color:#a6e22e>unsafe</span>.<span style=color:#a6e22e>Pointer</span>(<span style=color:#a6e22e>outToken</span>)),
</span></span><span style=display:flex><span> )
</span></span><span style=display:flex><span> <span style=color:#66d9ef>if</span> <span style=color:#a6e22e>ret</span> <span style=color:#f92672>==</span> <span style=color:#ae81ff>0</span> {
</span></span><span style=display:flex><span>  <span style=color:#66d9ef>if</span> <span style=color:#a6e22e>err</span> <span style=color:#f92672>==</span> <span style=color:#ae81ff>0</span> {
</span></span><span style=display:flex><span>   <span style=color:#a6e22e>err</span> = <span style=color:#a6e22e>syscall</span>.<span style=color:#a6e22e>EINVAL</span>
</span></span><span style=display:flex><span>  }
</span></span><span style=display:flex><span>  <span style=color:#66d9ef>return</span> <span style=color:#a6e22e>err</span>
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> <span style=color:#66d9ef>nil</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><ul><li>auth.go</li></ul><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#75715e>// +build !windows
</span></span></span><span style=display:flex><span><span style=color:#75715e></span>
</span></span><span style=display:flex><span><span style=color:#f92672>package</span> <span style=color:#a6e22e>auth</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>func</span> <span style=color:#a6e22e>Auth</span>(<span style=color:#a6e22e>user</span>, <span style=color:#a6e22e>password</span> <span style=color:#66d9ef>string</span>) <span style=color:#66d9ef>error</span> {
</span></span><span style=display:flex><span>    <span style=color:#66d9ef>return</span> <span style=color:#66d9ef>nil</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><h4 id=编译>编译</h4><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>GOOS<span style=color:#f92672>=</span>windows GOARCH<span style=color:#f92672>=</span>amd64 go build -o auth.exe main.go
</span></span></code></pre></div><h4 id=usage>Usage</h4><p><figure><img src=https://static.vimiix.com/uPic/2021-03-22/image-20210322221809864.png alt=image-20210322221809864></figure></p><h4 id=golang-相关的库>golang 相关的库</h4><ul><li><a href=https://github.com/golang/sys/blob/77190671981848ff71219ecfff38636c9add3b79/windows/dll_windows.go>https://github.com/golang/sys/blob/77190671981848ff71219ecfff38636c9add3b79/windows/dll_windows.go</a></li><li><a href=https://github.com/itchio/ox>https://github.com/itchio/ox</a></li><li><a href=https://github.com/lxn/win>https://github.com/lxn/win</a></li><li><a href=https://github.com/JamesHovious/w32>https://github.com/JamesHovious/w32</a></li></ul><h4 id=参考链接>参考链接</h4><ul><li><p><a href=https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-logonuserw>https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-logonuserw</a></p></li><li><p><a href=https://knowledgebase.progress.com/articles/Article/P21685>https://knowledgebase.progress.com/articles/Article/P21685</a></p></li><li><p><a href=https://bbs.csdn.net/topics/360202554>https://bbs.csdn.net/topics/360202554</a></p></li></ul></div></article></main><aside><div><div><h3>LATEST POSTS</h3></div><div><ul><li><a href=/posts/2025-10-16-kubernetes-apiserver-authorization-mechanism/>Kubernetes APIServer 鉴权机制</a></li><li><a href=/posts/2025-09-30-kubernetes-apiserver-authentication-mechanism/>Kubernetes APIServer 认证机制</a></li><li><a href=/posts/2024-12-16-deploy-kubernetes-by-kubeadm/>使用 kubeadm 搭建 kubernetes 集群</a></li><li><a href=/posts/2024-09-20-how-to-code-review/>如何做code review</a></li><li><a href=/posts/2024-08-12-weakref-in-python/>Python中的弱引用</a></li></ul></div></div></aside><footer><p>Social Links:
<a href=https://github.com/vimiix><b>Github</b></a>.
<a href=https://www.douban.com/people/vimiix/><b>Douban</b></a>.
<a href=mailto:i@vimiix.com><b>Email</b></a>.<br><hr>&copy; 2017-2025
Vimiix Yao; All rights reserved.
<a href=https://beian.miit.gov.cn/>京ICP备19015214号-1</a></p><script src=https://l2dwidget.js.org/lib/L2Dwidget.min.js></script><script>L2Dwidget.init({model:{jsonPath:"https://unpkg.com/live2d-widget-model-tororo@1.0.5/assets/tororo.model.json"}})</script></footer></body></html>